﻿using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;

namespace OnlineStore
{
    public static class Log
    {
        //WinApi函数
        [DllImport("kernel32.dll")]
        private static extern Boolean AllocConsole();

        [DllImport("kernel32.dll")]
        private static extern Boolean FreeConsole();

        /// <summary>
        /// 输出颜色
        /// </summary>
        private enum MsgColor
        {
            Gray,
            Green,
            Yellow,
            Red
        }

        /// <summary>
        /// 多线程锁
        /// </summary>
        private static readonly object MLock = new object();

        /// <summary>
        /// 输出重定向
        /// </summary>
        private static FileStream _fileStream;

        private static StreamWriter _streamWriter;

        /// <summary>
        /// 创建控制台
        /// </summary>
        public static void CreateConsole()
        {
#if DEBUG
            AllocConsole();
#endif
        }

        /// <summary>
        /// 销毁控制台
        /// </summary>
        public static void ReleaseConsole()
        {
#if DEBUG
            FreeConsole();
#endif
        }

        /// <summary>
        /// 重定向到文件
        /// </summary>
        /// <param name="filePath">文件路径</param>
        public static void SetOutputFile(string filePath = "./log.txt")
        {
            _fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write);
            _streamWriter = new StreamWriter(_fileStream);
            Console.SetOut(_streamWriter);
        }

        /// <summary>
        /// 输出白色消息
        /// </summary>
        /// <param name="format">需要输出的内容</param>
        /// <param name="args">要使用 format 写入的对象的数组</param>
        public static void Info(string format, params object[] args)
        {
            WriteMessage(MsgColor.Gray, format, args);
        }

        /// <summary>
        /// 输出白色消息
        /// </summary>
        /// <param name="format">需要输出的内容</param>
        public static void Info(string format)
        {
            WriteMessage(MsgColor.Gray, format, new { });
        }

        /// <summary>
        /// 输出白色消息
        /// </summary>
        /// <param name="format">需要输出的内容</param>
        /// <param name="title">输出信息的开头</param>
        public static void Info(string format, string title)
        {
            format = $"{title} ==> {format}";
            WriteMessage(MsgColor.Gray, format, new { });
        }

        /// <summary>
        /// 输出绿色消息
        /// </summary>
        /// <param name="format">需要输出的内容</param>
        /// <param name="args">要使用 format 写入的对象的数组</param>
        public static void Suc(string format, params object[] args)
        {
            WriteMessage(MsgColor.Green, format, args);
        }

        /// <summary>
        /// 输出绿色消息
        /// </summary>
        /// <param name="format">需要输出的内容</param>
        public static void Suc(string format)
        {
            WriteMessage(MsgColor.Green, format, new { });
        }

        /// <summary>
        /// 输出绿色消息
        /// </summary>
        /// <param name="format">需要输出的内容</param>
        /// <param name="title">输出信息的开头</param>
        public static void Suc(string format, string title)
        {
            format = $"{title} ==> {format}";
            WriteMessage(MsgColor.Green, format, new { });
        }

        /// <summary>
        /// 输出黄色消息
        /// </summary>
        /// <param name="format">需要输出的内容</param>
        /// <param name="args">要使用 format 写入的对象的数组</param>
        public static void Warning(string format, params object[] args)
        {
            WriteMessage(MsgColor.Yellow, format, args);
        }

        /// <summary>
        /// 输出黄色消息
        /// </summary>
        /// <param name="format">需要输出的内容</param>
        public static void Warning(string format)
        {
            WriteMessage(MsgColor.Yellow, format, new { });
        }

        /// <summary>
        /// 输出黄色消息
        /// </summary>
        /// <param name="format">需要输出的内容</param>
        /// <param name="title">输出信息的开头</param>
        public static void Warning(string format, string title)
        {
            format = $"{title} ==> {format}";
            WriteMessage(MsgColor.Yellow, format, new { });
        }

        /// <summary>
        /// 输出红色消息
        /// </summary>
        /// <param name="format">需要输出的内容</param>
        /// <param name="args">要使用 format 写入的对象的数组</param>
        public static void Error(string format, params object[] args)
        {
            WriteMessage(MsgColor.Red, format, args);
        }

        /// <summary>
        /// 输出红色消息
        /// </summary>
        /// <param name="format">需要输出的内容</param>
        public static void Error(string format)
        {
            WriteMessage(MsgColor.Red, format, new { });
        }

        /// <summary>
        /// 输出红色消息
        /// </summary>
        /// <param name="format">需要输出的内容</param>
        /// <param name="title">输出信息的开头</param>
        public static void Error(string format, string title)
        {
            format = $"{title} ==> {format}";
            WriteMessage(MsgColor.Red, format, new { });
        }

        /// <summary>
        /// 写入信息
        /// </summary>
        /// <param name="color">字体颜色</param>
        /// <param name="format">需要输出的内容</param>
        /// <param name="args">要使用 format 写入的对象的数组</param>
        private static void WriteMessage(MsgColor color, string format, params object[] args)
        {
#if DEBUG
            lock (MLock)
            {
                switch (color)
                {
                    case MsgColor.Gray:
                        Console.ForegroundColor = ConsoleColor.Gray;
                        break;
                    case MsgColor.Green:
                        Console.ForegroundColor = ConsoleColor.Green;
                        break;
                    case MsgColor.Yellow:
                        Console.ForegroundColor = ConsoleColor.Yellow;
                        break;
                    case MsgColor.Red:
                        Console.ForegroundColor = ConsoleColor.Red;
                        break;
                    default:
                        Console.ForegroundColor = ConsoleColor.Gray;
                        break;
                }

                Console.WriteLine(format, args);
                Console.ForegroundColor = ConsoleColor.Gray;
            }
#endif
        }
    }
}